import { get, isEmpty } from 'lodash';
import { Op } from 'sequelize';
import BaseController from './base';
import HotelModel from '../models/hotel';
import ReservationRefundModel from '../models/reservation-refund';
import ReservationPrepayModel from '../models/reservation-prepay';
import ReservationResultModel from '../mongodb/models/wxpay-refund-result';
import { getSequelize } from '../db';
import { getWxPay } from '../utils/WxPay';
import { generateOutTradeNo, getHotelParameters } from '../utils';

// order docs https://sequelize.org/docs/v6/core-concepts/model-querying-basics/
class ReservationRefundController extends BaseController {

  constructor() {
    super();
    this.getSummary = this.getSummary.bind(this);
  }

  getModel() {
    return ReservationRefundModel;
  }

  /**
   * 解析查询条件
   * @returns {Object}
   */
  getFindWhere(req) {
    const {
      openid, room, primary_confirm_number, confirm_number, begin_date, end_date
    } = req.query;

    const { hotel_id } = req.user;
    const sequelize = getSequelize();

    const where = {
      hotel_id,
      business_date: {
        [Op.between]: [begin_date, end_date]
      }
    };

    if (openid) {
      where.openid = openid;
    }

    if (room) {
      where.room = room;
    }

    if (primary_confirm_number) {
      where.primary_confirm_number = primary_confirm_number;
    }

    if (confirm_number) {
      // where.room = room;
      where[Op.and] = sequelize.where(sequelize.fn('FIND_IN_SET', confirm_number, sequelize.col('confirm_number')), '>', 0)
    }

    return { where };
  }

  /*
  result 正确示例
  {
    status: 200,
    data: {
      amount: {
        currency: 'CNY',
        discount_refund: 0,
        from: [],
        payer_refund: 10,
        payer_total: 2420,
        refund: 10,
        refund_fee: 0,
        settlement_refund: 10,
        settlement_total: 2420,
        total: 2420
      },
      channel: 'ORIGINAL',
      create_time: '2024-07-03T15:07:06+08:00',
      funds_account: 'AVAILABLE',
      out_refund_no: '202407031507055768078327228',
      out_trade_no: '202407031217143252271553304',
      promotion_detail: [],
      refund_id: '50310209922024070304562533850',
      status: 'PROCESSING',
      transaction_id: '4200002341202407037301422721',
      user_received_account: '招商银行信用卡2311'
    }
  }

  */
  async create(req, res, next) {
    try {
      const { hotel_id } = req.user;
      const { reservation_prepay_id, reason, refund_amount, reference, post_to_pms } = req.body;
      const reservationPepay = await ReservationPrepayModel.findOne({
        where: {
          id: reservation_prepay_id
        },
        rejectOnEmpty: new Error('未找到支付记录')
      });

      const hotel = await HotelModel.findOne({
        where: {
          id: hotel_id
        },
        raw: true
      });

      const keyParams = await getHotelParameters(hotel);
      if (!get(keyParams, 'WXREFUND_NOTIFY_URL')) {
        throw new Error('未设置微信退款通知链接参数')
      }
      const pay = getWxPay(hotel);

      const out_refund_no = generateOutTradeNo();
      const result = await pay.refunds({
        transaction_id: reservationPepay.wx_transaction_id,
        // out_trade_no: reservationPepay.out_trade_no,  // transaction_id与out_trade_no二选一 不能同时传
        out_refund_no,
        reason,
        notify_url: get(keyParams, 'WXREFUND_NOTIFY_URL'),
        amount: {
          total: reservationPepay.amount * 100,
          refund: refund_amount * 100,
          currency: 'CNY',
        },
      });
      if (result.status !== 200) {
        throw new Error(result.error)
      }

      console.log(result)
      const model = this.getModel();
      const data = await model.create({
        reservation_prepay_id,
        hotel_id: reservationPepay.hotel_id,
        openid: reservationPepay.openid,
        appid: reservationPepay.appid,
        mchid: reservationPepay.mchid,
        confirm_number: reservationPepay.confirm_number,
        resv_name_id: reservationPepay.resv_name_id,
        primary_confirm_number: reservationPepay.primary_confirm_number,
        primary_resv_name_id: reservationPepay.primary_resv_name_id,
        out_trade_no: reservationPepay.out_trade_no,
        wx_transaction_id: reservationPepay.wx_transaction_id,
        reason,
        reference,
        out_refund_no,
        refund_id: result.data.refund_id,
        refund_amount,
        channel: result.data.channel,
        user_received_account: result.data.user_received_account,
        refund_status: result.data.status,
        funds_account: result.data.funds_account,
        post_to_pms,
      });
      ReservationResultModel.create(result.data);
      res.sendOk(data);
    } catch (e) {
      next(e);
    }
  }

  async getSummary(req, res, next) {
    try {
      const squelize = getSequelize();
      const where = this.getFindWhere(req);
      const data = await ReservationPrepayModel.findAll({
        attributes: [[squelize.fn("SUM", squelize.col("refund_amount")), "refund_amount"]],
        ...where
      });

      res.sendOk(data);
    } catch (e) {
      next(e);
    }
  }
}

export default new ReservationRefundController();
